// Copyright (C)2012 Johann Duscher. All rights reserved.
//
// This file is part of QwTAPI.
//
// QwTAPI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// QwTAPI is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with QwTAPI.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include "stdafx.h"

#include "LineListener.h"


namespace qwtapi
{

class Connection;
class Call;
class Address;
class Request;

class QWTAPI_EXPORT Line : public LineListener
{
    Q_OBJECT

    typedef LineListener super;

    friend class Call;

public:
    typedef QList<Call*> CallList;
    typedef QList<Address*> AddressList;

    Line(Connection *pParent);
    ~Line();

    Connection* getConnection() const;

    LONG initialize(DWORD deviceId);
    DWORD getAddressCount() const;
    HLINE getLineHandle() const;
    DWORD getDeviceId() const;
    DWORD getNegotiatedAPIVersion() const;

    LONG open(CallPrivilege::Constants callPrivileges, MediaMode::Constants mediaModes, DWORD apiVersion = 0, DWORD extVersion = 0, LPLINECALLPARAMS const pCallParams = NULL);
    bool isOpen() const;
    LONG close();

    QString getName() const;
    const LPLINEDEVCAPS getCapabilities() const;
    LONG refreshCapabilities(DWORD apiVersion = 0, DWORD extVersion = 0);

    Call* allocateCall(HCALL hCall);
    Call* findCallForHandle(HCALL hCall) const;

    Address* getAddressFromId(DWORD addressId) const;
    QString getServiceProviderInfo() const;

    LONG makeCall(const QString& destAddress, DWORD country = 0, LPLINECALLPARAMS const pCallParams = NULL);

    CallList getCalls() const;

    void onLineEvent(DWORD hDevice, Message::Constant msg, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
    void onForceClose();

signals:
    void tapiLineEvent(DWORD hDevice, Message::Constant msg, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);

protected:
    bool deallocateCall(Call* pCall);

    void gatherAddressInformation();

    void onClose();

    void onAppNewCall(DWORD addressId, HCALL hCall, CallPrivilege::Constant privilege);
    void onCallInfo(HCALL hCall, CallInfoState::Constants callInfoState);
    void onCallState(HCALL hCall, CallState::Constant callState, DWORD callStateDetail, CallPrivilege::Constant callPrivilege);

protected slots:
    void onMakeCallResult(const Request* pRequest);

private:
    HLINE m_hLine;
    DWORD m_deviceId;
    DWORD m_apiVersion;
    mutable LPLINEDEVCAPS m_pLineCaps;   // Cached line capabilities.
    mutable LPLINEDEVSTATUS m_pLineStatus; // Last read line status.
    
    mutable QMutex m_callListMutex;
    CallList m_callList;

    mutable QMutex m_addressListMutex;
    AddressList m_addressList;
};

}
